/*
 * Created by kopper on 01.02.15 08:44
 * (C) Copyright 2015 kopperek@gmail.com
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 */

package app.android.kopper.gpxdownloader.parser;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
import java.util.Calendar;

import app.android.kopper.gpxdownloader.IUtilProvider;
import app.android.kopper.gpxdownloader.ProgressParam;
import app.android.kopper.gpxdownloader.R;

public class MG650Parser extends AbstractParser {

    public MG650Parser(File file, long fileSize) {
        super(file,fileSize);
    }

    @Override
	protected void performParsing(IUtilProvider utils) throws IOException, FileNotFoundException {
		
		long endOffsets[]=new long[512];
		Arrays.fill(endOffsets,0);
        int noOfTracks;
        for(noOfTracks=0;noOfTracks<512;noOfTracks++) {
			byte[] offset = loadArray(4,utils);
			if(!Arrays.equals(offset,new byte[]{(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}))
			{
				endOffsets[noOfTracks] = extractLong(offset);
				loadArray(12,utils); //note: sth interesting?
			} else
                break;
		}
		seekTo(0x2000,utils);
		
		PrintWriter gpxWriter=null; 
		
		loop:
		for(int a=0;a<noOfTracks;a++) {
            utils.publishProgress(new ProgressParam(utils.getString(R.string.progress_parsing),String.format(utils.getString(R.string.progress_track_no),a+1),a,noOfTracks));
            long endOffset = endOffsets[a];
			if(endOffset==0)
				break;
			for(;;) {
                if(filePos==endOffset) {
					closeGpxWriter(gpxWriter);
					gpxWriter=null;
					continue loop;
				}
				PointDef point = loadPoint(utils);
				if(gpxWriter==null)
					gpxWriter=createGpxWriter(createGpxFileName(point),utils);
				writeTrackPoint(gpxWriter, point);
			}
		}
		
//		System.out.println(endOffset);
		
	}

	private PointDef loadPoint(IUtilProvider utils) throws IOException {
		byte[] time = loadArray(4,utils);
		
		Calendar c=Calendar.getInstance();
		c.set(Calendar.YEAR,(int) (2006+readBits(time,6)));
		c.set(Calendar.MONTH,(int) readBits(time,4));
		c.set(Calendar.DAY_OF_MONTH,(int) readBits(time,5));
		c.set(Calendar.HOUR,(int) readBits(time,5));
		c.set(Calendar.MINUTE,(int) readBits(time,6));
		c.set(Calendar.SECOND,(int) readBits(time,6));
		c.set(Calendar.MILLISECOND,0);
		
		float lon = ByteBuffer.wrap(loadArray(4,utils)).order(ByteOrder.LITTLE_ENDIAN).getFloat();
		float lat = ByteBuffer.wrap(loadArray(4,utils)).order(ByteOrder.LITTLE_ENDIAN).getFloat();
		loadArray(4,utils);
		return(new PointDef(c.getTime(),lat,lon));
	}
	

	public static long readBits(byte[] array, int lenght) {
		long result=0;
		for(int a=0;a<lenght;a++) {
			result=(result<<1)+((array[0]&0xff)>>7);
			shiftArray(array);
		}
		return(result);
	}

	public static void shiftArray(byte[] array) {
		int lastCarryBit=0;
		for(int b=array.length-1;b>=0;b--) {
			byte carryBit = (byte) ((array[b]&0xff)>>7);
			array[b]=(byte) ((array[b]<<1)|lastCarryBit);
			lastCarryBit=carryBit;
		}
	}
}
